﻿// Inner Fire 游戏引擎库
// 渲染项目类-基础渲染管理器
//
// Copyright (c) 2024 by 尔西大帝. All rights reserved.
//
// 用于UI中的基础渲染管理器。Image和Text渲染管理器都继承此类
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-12-24

#include "ui_mesh.h"

#include <array>
#include <graphics/vertex.h>

namespace ifire::dx {

///////////////////////////////////////////////////////////////////////////////
// UIMesh
///////////////////////////////////////////////////////////////////////////////
static constexpr int IMAGE_VERTEX_COUNT = 4;
static constexpr int IMAGE_INDEX_COUNT = 6;

UIMesh::UIMesh(const UIMeshDesc& desc)
    : client_size_(desc.ClientSize), capacity_(desc.Capacity), size_(0) {
  half_size_ = {client_size_.x / 2.0f, client_size_.y / 2.0f};
  // TIPS:
  // TODO: 等下调试好之后，要把多余的size和us_size删除了。这个在实例化数据里面。
  // 所有的Image都使用同样的一顶点和索引，而使用实例化进行绘制。原始和顶点和索引是不变的。
  // 使用UIVertex表示的时候，各成员的意义如下：
  // pos = 顶点的NDC位置
  //       如果从玩家视角看去，这应该是一个覆盖整个屏幕的面片。
  // size = 没有意义，不需要赋值，都赋值0,0。
  // us_pos = 顶点的UV位置
  // us_size = 没有意义，不需要赋值，都赋值0,0。
  // 这里不用担心数值空间的浪费，因为只有一个。

  // 此项目的顶点
  eastl::vector<UIVertex> vertices = {{
      {XMFLOAT2(-1.0f, -1.0f), XMFLOAT2(0.0f, 0.0f)}, // 左下角
      {XMFLOAT2(1.0f, -1.0f), XMFLOAT2(1.0f, 0.0f)},  // 右下角
      {XMFLOAT2(1.0f, 1.0f), XMFLOAT2(1.0f, 1.0f)},   // 右上角
      {XMFLOAT2(-1.0f, 1.0f), XMFLOAT2(0.0f, 1.0f)}   // 左上角
  }};
  // 此项目的索引
  eastl::vector<std::uint16_t> indices = {0, 1, 2, 0, 2, 3};

  // 将顶点和索引建立为缓冲区
  mesh_ = std::make_unique<DxMesh>(0, "UI");
  dx::DxMeshCreateDesc create_desc{};
  create_desc.pVertexData = vertices.data();
  create_desc.pIndexData = indices.data();
  create_desc.VertexSize = vertices.size();
  create_desc.VertexStrideSize = sizeof(UIVertex);
  create_desc.IndexSize = indices.size();
  create_desc.IndexFormat = DXGI_FORMAT_R16_UINT;
  create_desc.IndexStrideSize = sizeof(std::uint16_t);
  mesh_->CreateResource(desc.pDevice, desc.pCmdList, create_desc);
  mesh_->AddSubmesh("Default", 0, 0, IMAGE_INDEX_COUNT, 0, 0);
}

size_t UIMesh::AllocVertex(size_t count) {
  size_t index = size_;
  size_ += count;
  return index;
}

void UIMesh::Draw(
    UploadBuffer<UIInstancedData>* uploader, ID3D12GraphicsCommandList* cmd) {
  // 绑定顶点与索引（因为都使用同一个，所以直接绑定）
  auto vertex_view = mesh_->VertexBufferView();
  cmd->IASetVertexBuffers(0, 1, &vertex_view);
  auto index_view = mesh_->IndexBufferView();
  cmd->IASetIndexBuffer(&index_view);
  cmd->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

  cmd->DrawIndexedInstanced(
      IMAGE_INDEX_COUNT, static_cast<UINT>(size_), 0, 0, 0);
}


} // namespace ifire::dx